--[[## ft=lua ##################################################################
  This file is licensed under [WTFPL v2](https://www.wtfpl.net/).  You may read
  the full license in the file LICENSE or by following the web link.

  STRINGX - extensions to string operations in Lua.

  This is a collection of miscellaneous routines to use as a drop-in replacement
  for the standard string library.  For convenience, the standard string library
  is shadowed thus permitting the following in code:

    local string = require 'stringx'

  This lets all current string operations get used in parallel with the
  extensions in a seamless fashion.
--############################################################################]]

--[[####################################
  Import required modules.
--####################################]]
local string = require 'string'

--[[####################################
  Copy required functions.
--####################################]]
local str_format = string.format
local str_gmatch = string.gmatch
local str_gsub = string.gsub
local str_len = string.len
local str_match = string.match

--[[####################################
  Useful patterns.
--####################################]]
local pure_ascii = '[\0-\x7f]+'


--[[####################################
  Shadow the standard library.
--####################################]]
local mt = {
    __index = string
}
local M = setmetatable({}, mt)

--[[####################################
  Assorted supplemental string operations.
--####################################]]

--[[################
  Concatenate a list of strings with a separator between members.
--################]]
local function concat(mem, sep)
    local n = #mem
    local ret = ''

    if n > 0 then
        ret = mem[1]
        for i = 2, n do
            ret = ret .. sep .. mem[i]
        end
    end

    return ret
end
M.concat = concat

--[[################
  Count the number of characters in a string which match a given pattern.
--################]]
local function count_matching(str, pat)
    local count = 0
    for match in str_gmatch(str, pat) do
        count = count + str_len(match)
    end
    return count
end
M.count_matching = count_matching

--[[################
  Extract the characters in a string which match a given pattern.
--################]]
local function extract_matching(str, pat)
    local rv = ""
    for match in str_gmatch(str, pat) do
        rv = rv .. match
    end
    return rv
end
M.extract_matching = extract_matching

--[[################
  Split a string according to a separator pattern.
--################]]
local function split(str, sep)
    local lsep = sep or ':'
    local mem = {}
    local pat = str_format('([^%s]+)', lsep)

    str_gsub(str, pat, function(ch) mem[#mem + 1] = ch end)

    return mem
end
M.split = split

--[[################
  Trim a string of leading and closing white.
--################]]
local function trim(str)
    str_match(str, '^[%s]*(.-)[%s]*$')
end
M.trim = trim

return setmetatable({}, { __index = M })
